import { useState, useCallback, useMemo, Children, useRef } from 'react';
import { View } from '@tarojs/components';
import classNames from 'classnames';
import Layout from '../Layout';
import ScrollView from '../ScrollView';
import Absolute from '../Absolute';
import Text from '../Text';
import Column from '../Column';
import Row from '../Row';
import Icon from '../Icon';
import BoxShadow from '../BoxShadow';
import Space from '../Space';
import './index.scss';

const TabItem = ({ id, type, buttonColor, buttonRound, title, paneKey, select, onClick, isExpand, scroll }) => {
  const [hover, setHover] = useState(false);
  if (type === 'button') {
    return (
      <Column
        self='center'
        className={classNames(
          'pd-tab__item--button',
          buttonColor && 'pd-tab__item--button-c-' + buttonColor,
          buttonRound && 'pd-tab__item--button-round',
          select && 'pd-tab__item--button-select',
          isExpand && 'pd-tab__item--button-expand',
          hover && 'pd-tab__item--button-hover',
        )}
        id={id}
        onClick={() => onClick(paneKey)}
        onTouchStart={() => setHover(true)}
        onTouchEnd={() => setHover(false)}
        onTouchMove={() => setHover(false)}>
        <Text color={select ? 4 : 1} size={4}>
          {title}
        </Text>
      </Column>
    );
  }

  return (
    <Column
      id={id}
      self='center'
      className={classNames({
        'pd-tab__item': scroll,
        'pd-tab__item-hover': hover,
      })}
      items='center'
      justify='center'
      onClick={() => onClick(paneKey)}
      onTouchStart={() => setHover(true)}
      onTouchEnd={() => setHover(false)}
      onTouchMove={() => setHover(false)}>
      <Text type={select ? 'primary' : void 0} color={select ? void 0 : 2} bold size={4}>
        {title}
      </Text>
      <View className={classNames('pd-tab__item__line', select && 'pd-tab__item__line--hover')} />
    </Column>
  );
};

const Scroll = ({ scrollIntoView, scroll, style, children }) => {
  if (scroll) {
    return (
      <ScrollView.Horizontal style={style} scrollIntoView={scrollIntoView} scrollWithAnimation>
        {children}
      </ScrollView.Horizontal>
    );
  }
  return (
    <Row className='pd-tab__row' items='center' justify='around' style={style}>
      {children}
    </Row>
  );
};

const Tab = ({
  value,
  disabled,
  onChange,
  type = 'line',
  buttonColor,
  buttonRound,
  defaultValue,
  scroll,
  justify,
  expand,
  lazyload,
  style,
  tabStyle,
  className,
  children,
  ...props
}) => {
  const [layout, setLayout] = useState({});

  const [showExpand, setShowExpand] = useState(false);

  const [list, tabPane] = useMemo(() => {
    const _tabPane = [];
    const _list = Children.map(children, (_child, index) => {
      const paneKey = _child?.props?.paneKey ?? index;
      _tabPane[index] = {
        paneKey,
        el: _child?.props.children,
      };
      return {
        ..._child?.props,
        paneKey,
      };
    });
    return [_list, _tabPane];
  }, [children]);

  const [select, setSelect] = useState(value ?? defaultValue ?? list?.[0]?.paneKey);

  // 懒加载模式记录哪些tab被加载了
  const shows = useRef([]);
  if (!shows.current.includes(select)) {
    shows.current.push(select);
  }

  const preIdRef = useRef(
    'tab_' +
      Math.floor(Math.random() * 1000000)
        .toString()
        .slice(0, 6) +
      '_',
  );

  useMemo(() => {
    if (typeof value !== 'undefined') {
      setSelect(value);
    }
  }, [value]);

  const scrollIntoView = useMemo(() => {
    if (!scroll) return undefined;
    return preIdRef.current + select;
  }, [list, select, preIdRef.current, scroll]);

  const change = useCallback(
    async i => {
      if (disabled) {
        return;
      }
      const res = onChange?.(i);
      if (res instanceof Promise) {
        await res;
      }
      setSelect(i);
      setShowExpand(false);
      setLayout({});
    },
    [onChange, disabled],
  );

  const tabs = (
    <Scroll scroll={scroll} style={tabStyle} scrollIntoView={scrollIntoView}>
      {list.map((item, index) => (
        <TabItem
          id={preIdRef.current + item.paneKey}
          type={type}
          buttonColor={buttonColor}
          buttonRound={buttonRound}
          key={item.paneKey || index}
          scroll={scroll}
          {...item}
          select={item.paneKey === select}
          onClick={change}
        />
      ))}
    </Scroll>
  );

  return (
    <View className={classNames(Tab, className, justify && 'flex-grow')} style={style} {...props}>
      {expand && scroll ? (
        <Layout className='flex-row' onLayout={e => showExpand && setLayout(e)} reloadKey={showExpand ? 1 : 0}>
          <Column grow>
            <Column className='inset-0 absolute' justify='center' items='center'>
              {tabs}
            </Column>
          </Column>
          <BoxShadow className='pd-tab__expand' x={-10} onClick={() => setShowExpand(true)}>
            <Text size={48}>
              <Icon name='more' />
            </Text>
          </BoxShadow>
          {showExpand && !!layout.width && (
            <Absolute>
              <Column className='pd-tab__expand__mask-top absolute left-0 right-0 top-0' style={{ height: layout.top }} />
              <Column
                className='pd-tab__expand__mask absolute left-0 right-0 bottom-0'
                style={{ top: layout.top }}
                onClick={() => {
                  setShowExpand(false);
                  setLayout({});
                }}
              />
              <Space row wrap className='pd-tab__expand__content absolute left-0 right-0' style={{ top: layout.top }}>
                {list.map((item, index) => (
                  <TabItem
                    type={type}
                    buttonColor='page'
                    buttonRound={buttonRound}
                    key={item.paneKey || index}
                    {...item}
                    isExpand
                    select={item.paneKey === select}
                    onClick={change}
                  />
                ))}
              </Space>
            </Absolute>
          )}
        </Layout>
      ) : (
        tabs
      )}
      {tabPane.some(v => typeof v.el !== 'undefined') && (
        <View className='pd-tab__con'>
          {tabPane.map((item, index) => (
            <View
              key={item.paneKey || index}
              className={classNames('pd-tab__con__item', item.paneKey === select && 'pd-tab__con__item--select')}>
              {(!lazyload || shows.current.includes(item.paneKey || index)) && item.el}
            </View>
          ))}
        </View>
      )}
    </View>
  );
};

Tab.Item = TabItem;
export default Tab;
